package es.uji.viselab.network.links;

import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;

import es.uji.viselab.ViSeLabException;
import es.uji.viselab.network.DataPackage;
import es.uji.viselab.network.EncoderDecoder;

public class VispEncoderDecoder implements EncoderDecoder {

	static String strBeginning = "[*start*]";
	static String strSeparator = "[*@*]";
	static String strEnd = "[*end*]";
	static String strParamSeparator = "[*|*]";

	public VispEncoderDecoder() {
		super();
	}

	@Override
	public String encode(List<DataPackage> data) {
		Iterator<DataPackage> iterator = data.iterator();
		String message = "";
		while (iterator.hasNext()) {
			DataPackage item = iterator.next();
			message = message + encode(item);
		}
		return message;
	}

	@Override
	public String encode(DataPackage item) {

		String message = null;
		String text = null;
		message = strBeginning + strSeparator;
		text = "            " + item.getType();
		text = text.substring(text.length() - 12);
		message = message + text;

		text = "000000000000" + String.valueOf(item.getSequence());
		text = text.substring(text.length() - 12);
		message = message + strParamSeparator + text;

		for (int i = 1; i <= item.getLenght(); i++) {
			Double dval = item.getValue(i);
			dval = dval * 1000000;
			long lval = dval.longValue();
			text = "000000000000" + lval;
			text = text.substring(text.length() - 12);
			message = message + strParamSeparator + text;
		}
		message = message + strEnd;
		return message;
	}

	@Override
	public List<DataPackage> decode(String s) throws ViSeLabException {
		// The string received can contain 1..n packets
		List<String> packageList = extractPackages(s);

		// Each packet, contains the data to incorporate to DataNetwork
		Iterator<String> iterator = packageList.iterator();
		// All of them, will be stored in a list of DataNetwork
		List<DataPackage> dataNetworkList = new ArrayList<DataPackage>();

		while (iterator.hasNext()) {
			List<String> stringDataList = extractData(iterator.next());
			DataPackage dataNetwork = new DataPackage(stringDataList);
			dataNetworkList.add(dataNetwork);
		}
		return dataNetworkList;
	}

	protected List<String> extractPackages(String data) {

		StringBuffer buffer = new StringBuffer(data);
		List<String> packagesList = new ArrayList<String>();
		String portion = null;

		boolean terminate = false;
		while (!terminate) {

			int start = 0;
			int end = buffer.indexOf(strEnd) + strEnd.length();
			if (end > 0) {
				try {
					portion = buffer.substring(start, end).toString();
				} catch (Exception e) {
					// log("Error");
				}
				buffer.delete(start, end);
				packagesList.add(portion);
				// dataNetwork data = network.decode(portion);
				// dataList.add(data);
				// log("x: " + data.getX() + " y " + data.getY() + " z "+
				// data.getZ());
				terminate = buffer.length() == 0;
			} else
				terminate = true;
		}
		return packagesList;

	}

	private String packData(List<String> list) {
		String message = null;
		message = strBeginning + strSeparator;
		Iterator<String> iterator = list.iterator();
		String text = iterator.next();
		text = "             " + text;
		text = text.substring(text.length() - 12);
		message = message + text;
		while (iterator.hasNext()) {
			Double val = Double.parseDouble(iterator.next());
			DecimalFormatSymbols otherSymbols = new DecimalFormatSymbols(Locale.getDefault());
			otherSymbols.setDecimalSeparator('.');
			DecimalFormat fmt = new DecimalFormat("#.#", otherSymbols);
			text = fmt.format(val);
			message = message + strParamSeparator + text;
		}
		message = message + strEnd;
		return message;
	}

	private List<String> extractData(String data) throws ViSeLabException {

		int start, end;
		// The ordered list of the parameters received
		List<String> parametersSet = new ArrayList<String>();
		String parameter;

		if (!(data.startsWith(strBeginning + strSeparator) & data.endsWith(strEnd))) {
			throw new ViSeLabException("Data to decode dont has the expected format",
					"Networ.decode();");
		}
		StringBuffer buffer = new StringBuffer(data);
		start = buffer.indexOf(strBeginning + strSeparator);
		end = (strBeginning.length() + strSeparator.length());
		buffer.delete(start, end);
		boolean endReached = false;
		while (!endReached) {
			start = 0;
			end = buffer.indexOf(strParamSeparator);
			if (end == -1)
				end = buffer.indexOf(strEnd);
			// extract the parameter from the buffer
			parameter = buffer.substring(start, end);
			// delete the just extracted parameter
			buffer.delete(start, end);
			// add the parameter to our set
			parametersSet.add(parameter);

			// System.out.println("Parameter found: " + parameter);

			// The next string can be the strSeparator or strEnd
			// anyway we should remove it to continue
			start = 0;
			if (buffer.indexOf(strEnd) == 0)
				endReached = true;
			else if (buffer.indexOf(strParamSeparator) == 0) {
				end = strSeparator.length();
				buffer.delete(start, end);
			}
		}

		return parametersSet;

	}

}
